//     _________________________________________
//    /                                        /
//   /    GTA SAN ANDREAS ENB BY ZENZOIT      /
//  /________________________________________/
//
//-------------------------------------------------------------------------------------------------]
//////////////////////////////////-----------------------------------------------------------------]
float4 ScreenSize = float4(1920,(1/1920),1080,(1/1080));
float4 Timer;
float FadeFactor;
//////////////////////////////////-----------------------------------------------------------------]

// gp65cj04 Skyrim Advanced Depth of Field
// IMPORTANT: enbseries.ini->AlternativeDepth = 1 !!!! otherwise it doesn't work.
//////////////////////////////////-----------------------------------------------------------------]

#define ADOF				

#ifdef ADOF

float DOFDepthLine = 0.9;				// Adjust depth of the border beyond which DOF starts
// Change in small increments! 0.9 means 5 metres distance, 0.8 means 100 metres distance


//#define	NOT_BLURRING_SKY_MODE			// not working	
#define	DEPTH_OF_FIELD_QULITY 1  			// DOF Quality [higher also means more blur!]
#define	AUTO_FOCUS					// not working
#define TILT_SHIFT					// not working
#define POLYGONAL_BOKEH					// enable for polygonal bokeh shape, disable for circular Bokeh
#define	POLYGON_NUM 6					// e.g. 3 = triangle bokeh shape, 5 = pentagonal, 6 = hexagonal etc.

// for auto focus
float2	FocusPoint=float2(0.5, 0.5);			// not working
float	FocusSampleRange=1.00;				// not working
float	NearBlurCurve=10.00;				// not working
float	FarBlurCurve=10.00;				// not working
float	DepthClip=150.0;				// not working

// for static dof
float	FocalPlaneDepth=0.50;				// not working
float	FarBlurDepth=50.00;				// not working			

// for tilt shift
float	TiltShiftAngle=30.0;				// not working			

// common
float	BokehBias=0.1;					// Brightens up blurred areas
float	BokehBiasCurve=0.75;				// Curve of brightening
float	BokehBrightnessThreshold=0.95;			// Threshold for BokehBrightnessMultipiler
float	BokehBrightnessMultipiler=2.00;		// Brightens up blurred areas above BokehBrightnessThreshold
float	RadiusSacleMultipiler=3.9;			// Overall Blur control

// noise grain
float	NoiseAmount=0.0;				// DOF grain power
float	NoiseCurve=0.0;					// noise courve - power of darkening/brightening of pixels get stronger

float	ChromaticAberrationAmount=0.0;			// Lets the blurred areas look like the red-green shift of 3d images a bit
#endif



// Color washout, recreates the dull, dry and washed out colors GTA IV has by default
//////////////////////////////////-----------------------------------------------------------------]

#define COLORWASHOUT

float	ColorSaturation=0.32;				// Saturation control
float	ColorWashoutThreshold=0.85;			// Threshold above which colors get washed out
float	ColorWashoutPow=1.0;				// Effect Power
float	ColorWashoutAmount=1.0;				// Effect Amount
float   ColorDullnessAmount=1.0;			// Let the colors look linear like SA and GTA IV without ENB
float   ExpAdjustment=1.25;				// High Color Dullnessamount darkens screen, compensate with this here


// Chromatic Abberation & Lens Distortion code by SSontech, implementing in ENB by IceLaGlace
// convert and all stuff to have it here: me
//////////////////////////////////-----------------------------------------------------------------]

//#define CHROMATICABBERATION

#ifdef CHROMATICABBERATION
float ChromaticAmount = 0.015; 				// Amount of chromatic aberration on the edges
float LensSize = 0.55;   				// 0.5 = Original image size; 1.0 = Zoomed
float LensDistortion = 0.1;   				// Can be negative to stretch the image
float LensDistortionCubic = 0.1;			// similiar to above, better results if same like LensDistortion
#endif


//Image Noise, adds a slight (or not so slight, depends on settings) grain to the screen like
//when a TV has no signal but far not so intensive, gives a movie-like feeling
//Original code by Matso
//////////////////////////////////-----------------------------------------------------------------]

//#define NOISE

#ifdef NOISE
#define SEED			Timer.w			//same
#define fGrainFreq 500.0				// image grain frequency, for some reason high values cause shadow flickering
#define fGrainScale 0.0001				// grain effect scale
#endif

//Anamorphic Lens Flare: Matso // Implementation, Tweaks, Fixes by Marty McFly
//////////////////////////////////-----------------------------------------------------------------]

#define MATSO_FLARE
#define fFlareLuminance 0.95				// bright pass luminance value 
#define fFlareBlur 1000.0				// manages the size of the flare
#define fFlareIntensity 1.00				// effect intensity
#define fFlareTint	float3(0.1, 0.15, 1.0)		// effect tint
//#define fFlareVertical
#define fFlareHorizontal
const float FlareRadius = 1.0/256.0;

//Image Dithering
//Applies dithering to simulate more colors than your monitor can display. 
//This lessens banding artifacts (mostly caused by Vignette and enbpalette which got edited many times)
//Note: Screenshot filesize gets slightly bigger because now there are less areas with the same color
//Ported from SweetFX by Ceejay.dk
//////////////////////////////////-----------------------------------------------------------------]

#define USE_DITHER
float screen_size = 1920; 				// Horizontal screen resolution

//Vibrance
//Intelligently saturates (or desaturates if you use negative values) the pixels depending on their original saturation.
//Ported from SweetFX by Ceejay.dk
//////////////////////////////////-----------------------------------------------------------------]

#define VIBRANCEPASS
#ifdef VIBRANCEPASS
float Vibrance = 0.245; 					//[-1.0 to 1.0] 
#endif


// DKT70 HDR
//////////////////////////////////-----------------------------------------------------------------]

#define HDR

float Defog=0.000; 					// Strength of FogColor, higher = more.
float4 FogColor={0.0, 0.0, 0.0, 0.0}; 			// Lens-style color filters for Blue, Red, Yellow, White.
float Exposure=0.90; 					// Contrast settings, higher = brighter, but also more white.
float Gamma=0.450; 					// Gamma settings for darker or lighter shadows and dark areas, higher = darker.
float BlueShift=0.25; 					// Shifts entire color spectrum towards blue, good for images too yellow, but this is global.

// DKT70 Sharpen effect
//////////////////////////////////-----------------------------------------------------------------]

//#define SHARPEN

float sharps = 0.0; 					//sharpen strength; always offset value x 2
float offsetv = 0.0;					//sharpen offset 
float sxres = 1920; 					// Horizontal Resolution setting x 2
float syres = 1080; 					// Vertical Resolution setting x 2
float aspect = 1.77777777778; 				// horizontal/vertical resolution


// COlormod-like bloom
//////////////////////////////////-----------------------------------------------------------------]

//#define COLORMODBLOOM

static const float fBloomThreshold = 7.0;
float fBloomIntensity =	 1.145; 	
const float BloomRadius = 1.0/64.0;			
const float BloomDownsampling = 128;
float BloomCurve =1.0;
//#define COLORBLOOM

// Light Scattering ("Godrays") implementation for SA by PetkaGtA, coloring by me
//////////////////////////////////-----------------------------------------------------------------]

//#define LIGHTSCATTERING
        
	//#define TINTCOLOR   				//Shifts godray color
	#define COLORING				//Colorizes godrays, original color gets lost
	#define REDAMOUNT  		1.2 		//power of red godray color
	#define GREENAMOUNT 		0.8 		//power of green godray color
	#define BLUEAMOUNT 		2.0 		//power of blue godray color
   
#ifdef LIGHTSCATTERING
float2 ScreenLightPos = {0.5,0.5};			//where the Godrays appear, 0.5, 0.5 means screen center
float Density = 1.50;					//power of the rays
static int NUM_SAMPLES = 128;				//how many samples
float Weight = 0.5;
float Decay = 1.0;
float SStresh = 0.938;					//pixel threshhold, above this level pixels get sampled, let it stay like this!
float SunExposure = 2.0;				//Sun gets brighter with this value
#endif


// Ministry of Games 0.1 filmic color correction by openzdl aka AAA (AgainstAllAuthority) convert by me
//////////////////////////////////-----------------------------------------------------------------]

#define FILMICPASS

#ifdef FILMICPASS
	float Strenght 		= 0.25;			//  from 0.0 to 1.0
	float BaseGamma 	= 1.6;			//  from 0.1.0 to 2.5
	float Fade		= 0.2;			//  from 0.0 to 0.5
	float Contrast		= 1.0;			//  from 0.6 to 1.0
	float Saturation	= -0.15;			//  from 0.25 to -0.25
	float Bleach		= 0.005;		//  from 0.0 to 1.0
	float RedCurve		= 6.0;			//  from 1.0 to 10.0
	float GreenCurve	= 6.0;			//  from 1.0 to 10.0
	float BlueCurve		= 6.0;			//  from 1.0 to 10.0
	float BaseCurve		= 1.5;			//  from 1.0 to 10.0
	float EffectGammaR	= 1.0;			//  from 0.1 to 2.5
	float EffectGammaG	= 1.0;			//  from 0.1 to 2.5
	float EffectGammaB	= 1.0;			//  from 0.1 to 2.5
	float EffectGamma	= 0.75;			//  from 0.1 to 2.5
	float Linearization	= 1.3;			//  from 1.0 to 2.5
#endif

//Reinhard tonemap. you have to get used to it, very strange look, 
//you have to build up your setting on it
//////////////////////////////////-----------------------------------------------------------------]

//#define REINHARD_ICE21
	#define REINHARD_SAT	 1.7 			//Saturation only for Reinhard tonemap
	#define TONEMAPEXP 	 3.4 			//Exposure only for Reinhard tonemap
	#define LUM_FACTOR 	float4(0.299, 0.587, 0.114, 0.0) //DON NOT CHANGE IT


// simple gamma Correction, lower = darker
//////////////////////////////////-----------------------------------------------------------------]

//#define GAMMACORRECTION
	#define GammaAmount       3.0 			//Gamma intensity

// the well-known filmiccurve (important: darkens screen really hard by default, I've added
// FilmicExposure which again turns up the brightness to a good amount. Changing the ABCDEFW values
// may require changing the FilmicExposure level
//////////////////////////////////-----------------------------------------------------------------]

//#define FILMICCURVE
	#ifdef FILMICCURVE
		float	FilmicExposure = 7;

//configuring the following stuff is very difficult, let it stay like this
//explanation is senseless because only the most advanced coders really understand 
//what each value does (not even me), maybe only the author. Set one to 10 and look what happens
//is the best way to get its effect

		float	ShoulderStrength = 0.50;
		float	LinearStrength = 0.50;
		float	LinearAngle = 0.30;
		float	ToeStrength = 2.50;
		float	ToeNumerator = 0.02;
		float	ToeDenominator = 1.50;
		float	WFilmWeight = 20.0; // 20

		float3 Uncharted2Tonemap(float3 x)
		{
			return ((x*(ShoulderStrength*x+LinearAngle*LinearStrength)+ToeStrength*ToeNumerator)/(x*(ShoulderStrength*x+LinearStrength)+ToeStrength*ToeDenominator))-ToeNumerator/ToeDenominator;
		}
	#endif

// HeliosDoubleSix (HD6) Vignette code
//////////////////////////////////-----------------------------------------------------------------]

//#define HD6_VIGNETTE
	#define LEFTANDRIGHT 				//only enable one of the three options here!
	//#define TOPANDBOTTOM 				//only enable one of the three options here!
	//#define CORNERDARKEN 				//only enable one of the three options here!
	#ifdef HD6_VIGNETTE
	float   SquareTop = 0.58;              		// TOP of Screen.
	float   SquareBottom = 0.58;   			// BOTTOM of Screen.
	float   CircularPower = 0.0;    		// CIRCULAR Vignette Amount.
	float   ColorDistortion = -0.666;  		// COLOR Distortion Strength.
	float   ContrastSharpen = 11.666;       	// Contrast & Sharpness Increase.
	float   VignetteBorder = 5.5;            	// High value means black bar, low means smooth gradient
	#endif

#define BORISVIGNETTE					//Le standard vignette

#ifdef BORISVIGNETTE
float	EVignetteAmount=2.5;				//Darkening/coloring power
float	EVignetteCurve=1.5;				//Vignette Curve (helpful huh? :D)
float	EVignetteRadius=0.8; 				//Radius beyond which the screen starts to get darkened/colored
	//#define VIGNCOLORING				//optional colorable vignette, ever wanted to make a red vignette or such? here you go

	#define VIGNREDAMOUNT		0.0		//self-explaining I think
	#define VIGNGREENAMOUNT		5.0		//self-explaining I think
	#define VIGNBLUEAMOUNT		0.0		//self-explaining I think
#endif

// Cross Processing by AAA, tries to recreate old TV look
//////////////////////////////////-----------------------------------------------------------------]

#define CROSSPROCESS
	#ifdef CROSSPROCESS
		float CrossContrast =1.0;		//Image contrast
		float CrossSaturation2 = 1.0;		//Image Saturation
		float CrossBrightness = 0.0;		//Image Brightness
		float CrossAmount = 2.0;		//amount of color changing
		float2 crossMatrix [3] =
		 {
			float2 (1.03, 0.04),
			float2 (1.09, 0.01),
			float2 (0.78, 0.13),
		 };
	#endif

// Cross Process by icelaglace, same like above but not as good 
//////////////////////////////////-----------------------------------------------------------------]

#define CROSSICE
	#ifdef CROSSICE
	float fRatio = 2.0;				//power of the color distortion
	float moodR = 0.4;				//preconfigured by ice
	float moodG = 0.30;				//preconfigured by ice
	float moodB = 0.05;				//preconfigured by ice
	#endif

//main color correction by me and openzdl aka AAA (AgainstAllAuthority)
//Remained in the shader for a long time, I don't want to remove it
//has no visible effect though
//////////////////////////////////-----------------------------------------------------------------]
//#define COLORCORRMAIN

// HSV-based Color Correction, looks much more difficult as it is :)	
//////////////////////////////////-----------------------------------------------------------------]

//#define HSVULTIMATE
#ifdef HSVULTIMATE
	#define ENABLE_HSV_CONVERSION  			// Enables HSV Conversion. Required for color controls below.
	#define ENABLE_SATURATION_ADJUSTMENT		// Enables color saturation control for the entire scene.
	#define ENABLE_INTENSITY_ADJUSTMENT  		// Enables brightness control for the entire scene.
	#define ENABLE_HUE_ADJUSTMENT    		// Enables hue control for the entire scene.
	#define ENABLE_COLOR_EQUALIZER    		// Enables the Color Equalizer system for advanced tweaking.

	//#define ENABLE_POW_CURVE    			// Enables power curve controls.

	// Color Saturation Variables
	float	EColorSaturationMod=0.0;  		// Adds to the overall color saturation. Range: -1 to 1. Default: 0.0
	float	EColorSaturationMult=1.0;  		// Multiplies the color saturation. Range: 0.0 (greyscale) to ???. Default: 1.0
	float	EColorSaturationPow=1.0;  		// Curves the color saturation. Range: 0.0 to ???. Default: 1.0

	// Color Intensity Variables
	float   EColorIntensityMod=0.0;  		// Adds to the overall brightness. Range: -1 to 1. Default: 0.0
	float   EColorIntensityMult=1.0;  		// Multiplies the color intensity. Range: 0.0 (black) to ???. Default: 1.0
	float   EColorIntensityPow=1.0;  			// Curves the color intensity. Range: 0.0 to ???. Default: 1.0

	// Color Hue Variables
	float   EColorHueMod=0.0;    			// Adds to the overall color hue (color shifting). Range: -1 to 1. Default: 0.0
	float   EColorHueMult=1.0;    			// Multiplies the color hue (color shifting). Range: 0.0 to ???. Default: 1.0
	float	EColorHuePow=1.0;    			// Curves the color hue. Range: 0.0 to ???. Default: 1.0.

	// Color Equalizer Variables
	// Adjust modifier to specific saturations. Range: -??? to ???. Default: 0.0
	float	SaturationModRed = 0.0;
	float	SaturationModOrange = 0.0;
	float	SaturationModYellow = 0.0;
	float	SaturationModGreen = 0.0;
	float	SaturationModCyan = 0.0;
	float	SaturationModBlue = 0.0;
	float	SaturationModMagenta = 0.0;

	// Adjust multiplier to specific saturations. Range: 0.0 to ???. Default: 0.0
	float	SaturationMultRed = 0.1;
	float	SaturationMultOrange = -0.2;
	float	SaturationMultYellow = 0.0;
	float	SaturationMultGreen = 0.2;
	float	SaturationMultCyan = -0.1;
	float	SaturationMultBlue = 0.0;
	float	SaturationMultMagenta = 0.1;

	// Adjust curve of specific saturations. Range: -1.0 to ???. Default: 0.0
	float	SaturationPowRed = 0.0;
	float	SaturationPowOrange = 0.0;
	float	SaturationPowYellow = 0.0;
	float	SaturationPowGreen = 0.0;
	float	SaturationPowCyan = 0.0;
	float	SaturationPowBlue = 0.0;
	float	SaturationPowMagenta = 0.0;
#endif

//////////////////////////////////-----------------------------------------------------------------]
//////////////////////////////////////////////
// DO NOT MODIFY ANYTHING BELOW THIS LINE,  //
// UNLESS YOU KNOW HLSL SHADER PROGRAMMING. //
//////////////////////////////////////////////
//////////////////////////////////-----------------------------------------------------------------]


#ifdef HSVULTIMATE
// List of floating point values for hues, used in equalizer.
float	HueRed = 0.0;
float	HueOrange = 0.08333333;
float	HueYellow = 0.16666667;
float	HueGreen = 0.33333333;
float	HueCyan = 0.5;
float	HueBlue = 0.66666667;
float	HueMagenta = 0.83333333;
float	HueRed2 = 1.0;

float	HueSkin = 0.07;
float	HueSky = 0.58;


float ColorEqualizerMult(in float H)
{
float SMult = 1.0;
SMult += SaturationMultRed * ( 1.0 - min( 1.0, abs( ( HueRed - H ) / ( HueRed - HueOrange ) ) ) );
SMult += SaturationMultOrange * ( 1.0 - min( 1.0, abs( ( HueOrange - H ) / ( HueOrange - HueYellow ) ) ) );
SMult += SaturationMultYellow * ( 1.0 - min( 1.0, abs( ( HueYellow - H ) / ( HueYellow - HueGreen ) ) ) );
SMult += SaturationMultGreen * ( 1.0 - min( 1.0, abs( ( HueGreen - H ) / ( HueGreen - HueYellow ) ) ) );
SMult += SaturationMultCyan * ( 1.0 - min( 1.0, abs( ( HueCyan - H ) / ( HueCyan - HueGreen ) ) ) );
SMult += SaturationMultBlue * ( 1.0 - min( 1.0, abs( ( HueBlue - H ) / ( HueBlue - HueCyan ) ) ) );
SMult += SaturationMultMagenta * ( 1.0 - min( 1.0, abs( ( HueMagenta - H ) / ( HueMagenta - HueBlue ) ) ) );
SMult += SaturationMultRed * ( 1.0 - min( 1.0, abs( ( HueRed2 - H ) / ( HueRed2 - HueMagenta ) ) ) );
return SMult;
}

float ColorEqualizerMod(in float H)	
{
float SMod = 0.0;
SMod += SaturationModRed * ( 1.0 - min( 1.0, abs( ( HueRed - H ) / ( HueRed - HueOrange ) ) ) );
SMod += SaturationModOrange * ( 1.0 - min( 1.0, abs( ( HueOrange - H ) / ( HueOrange - HueYellow ) ) ) );
SMod += SaturationModYellow * ( 1.0 - min( 1.0, abs( ( HueYellow - H ) / ( HueYellow - HueGreen ) ) ) );
SMod += SaturationModGreen * ( 1.0 - min( 1.0, abs( ( HueGreen - H ) / ( HueGreen - HueYellow ) ) ) );
SMod += SaturationModCyan * ( 1.0 - min( 1.0, abs( ( HueCyan - H ) / ( HueCyan - HueGreen ) ) ) );
SMod += SaturationModBlue * ( 1.0 - min( 1.0, abs( ( HueBlue - H ) / ( HueBlue - HueCyan ) ) ) );
SMod += SaturationModMagenta * ( 1.0 - min( 1.0, abs( ( HueMagenta - H ) / ( HueMagenta - HueBlue ) ) ) );
SMod += SaturationModRed * ( 1.0 - min( 1.0, abs( ( HueRed2 - H ) / ( HueRed2 - HueMagenta ) ) ) );
return SMod;
}

float ColorEqualizerPow(in float H)	
{
float SPow = 1.0;
SPow += SaturationPowRed * ( 1.0 - min( 1.0, abs( ( HueRed - H ) / ( HueRed - HueOrange ) ) ) );
SPow += SaturationPowOrange * ( 1.0 - min( 1.0, abs( ( HueOrange - H ) / ( HueOrange - HueYellow ) ) ) );
SPow += SaturationPowYellow * ( 1.0 - min( 1.0, abs( ( HueYellow - H ) / ( HueYellow - HueGreen ) ) ) );
SPow += SaturationPowGreen * ( 1.0 - min( 1.0, abs( ( HueGreen - H ) / ( HueGreen - HueYellow ) ) ) );
SPow += SaturationPowCyan * ( 1.0 - min( 1.0, abs( ( HueCyan - H ) / ( HueCyan - HueGreen ) ) ) );
SPow += SaturationPowBlue * ( 1.0 - min( 1.0, abs( ( HueBlue - H ) / ( HueBlue - HueCyan ) ) ) );
SPow += SaturationPowMagenta * ( 1.0 - min( 1.0, abs( ( HueMagenta - H ) / ( HueMagenta - HueBlue ) ) ) );
SPow += SaturationPowRed * ( 1.0 - min( 1.0, abs( ( HueRed2 - H ) / ( HueRed2 - HueMagenta ) ) ) );
return SPow;
}

float3 HUEtoRGB(in float H)
{
   float R = abs(H * 6.0 - 3.0) - 1.0;
   float G = 2.0 - abs(H * 6.0 - 2.0);
   float B = 2.0 - abs(H * 6.0 - 4.0);
   return saturate(float3(R,G,B));
}

float RGBCVtoHUE(in float3 RGB, in float C, in float V)
{
     float3 Delta = (V - RGB) / C;
     Delta.rgb -= Delta.brg;
     Delta.rgb += float3(2.0,4.0,6.0);
     Delta.brg = step(V, RGB) * Delta.brg;
     float H;
     H = max(Delta.r, max(Delta.g, Delta.b));
     return frac(H / 6.0);
}

float3 HSVtoRGB(in float3 HSV)
{
   float3 RGB = HUEtoRGB(HSV.x);
   return ((RGB - 1) * HSV.y + 1) * HSV.z;
}
 
float3 RGBtoHSV(in float3 RGB)
{
   float3 HSV = 0.0;
   HSV.z = max(RGB.r, max(RGB.g, RGB.b));
   float M = min(RGB.r, min(RGB.g, RGB.b));
   float C = HSV.z - M;
   if (C != 0.0)
   {
     HSV.x = RGBCVtoHUE(RGB, C, HSV.z);
     HSV.y = C / HSV.z;
   }
   return HSV;
}
#endif

#ifdef FILMICPASS
float GetLuminance(float3 sample)
	 {
		 return dot(sample.xyz, 0.333);
	 }
	 
float4 FilmPass(float4 B)
{
	float4 G = B;
	float4 H = 0.01;
 
	B = pow(abs(B), Linearization);
	B = lerp(H, B, Contrast);
 
	float A = GetLuminance(B.rgb);
	float4 D = A;
 
	B = pow(abs(B), 1.0 / BaseGamma);
 
	float a = RedCurve;
	float b = GreenCurve;
	float c = BlueCurve;
	float d = BaseCurve;
 
	float y = 1.0 / (1.0 + exp(a / 2.0));
	float z = 1.0 / (1.0 + exp(b / 2.0));
	float w = 1.0 / (1.0 + exp(c / 2.0));
	float v = 1.0 / (1.0 + exp(d / 2.0));
 
	float4 C = B;
 
	D.r = (1.0 / (1.0 + exp(-a * (D.r - 0.5))) - y) / (1.0 - 2.0 * y);
	D.g = (1.0 / (1.0 + exp(-b * (D.g - 0.5))) - z) / (1.0 - 2.0 * z);
	D.b = (1.0 / (1.0 + exp(-c * (D.b - 0.5))) - w) / (1.0 - 2.0 * w);
 
	D = pow(abs(D), 1.0 / EffectGamma);
 
	float4 Di = 1.0 - D;
 
	D = lerp(D, Di, Bleach);
 
	D.r = pow(abs(D.r), 1.0 / EffectGammaR);
	D.g = pow(abs(D.g), 1.0 / EffectGammaG);
	D.b = pow(abs(D.b), 1.0 / EffectGammaB);
 
	if (D.r < 0.5)
		C.r = (2.0 * D.r - 1.0) * (B.r - B.r * B.r) + B.r;
	else
		C.r = (2.0 * D.r - 1.0) * (sqrt(B.r) - B.r) + B.r;
 
	if (D.g < 0.5)
		C.g = (2.0 * D.g - 1.0) * (B.g - B.g * B.g) + B.g;
	else
		C.g = (2.0 * D.g - 1.0) * (sqrt(B.g) - B.g) + B.g;
 	//if (AgainstAllAutority) then fckoff else fckoff
	if (D.b < 0.5)
		C.b = (2.0 * D.b - 1.0) * (B.b - B.b * B.b) + B.b;
	else
		C.b = (2.0 * D.b - 1.0) * (sqrt(B.b) - B.b) + B.b;
 
	float4 F = lerp(B, C, Strenght);
 
	F = (1.0 / (1.0 + exp(-d * (F - 0.5))) - v) / (1.0 - 2.0 * v);
 
	float r2R = 1.0 - Saturation;
	float g2R = 0.0 + Saturation;
	float b2R = 0.0 + Saturation;
 
	float r2G = 0.0 + Saturation;
	float g2G = (1.0 - Fade) - Saturation;
	float b2G = (0.0 + Fade) + Saturation;
 
	float r2B = 0.0 + Saturation;
	float g2B = (0.0 + Fade) + Saturation;
	float b2B = (1.0 - Fade) - Saturation;
 
	float4 iF = F;
 
	F.r = (iF.r * r2R + iF.g * g2R + iF.b * b2R);
	F.g = (iF.r * r2G + iF.g * g2G + iF.b * b2G);
	F.b = (iF.r * r2B + iF.g * g2B + iF.b * b2B);
 
	float N = GetLuminance(F.rgb);
	float4 Cn = F;
 
	if (N < 0.5)
		Cn = (2.0 * N - 1.0) * (F - F * F) + F;
	else
		Cn = (2.0 * N - 1.0) * (sqrt(F) - F) + F;
 
	Cn = pow(abs(Cn), 1.0 / Linearization);
 
	float4 Fn = lerp(B, Cn, Strenght);
	return Fn;
}
#endif
//--------------------------------------------------------------------------------------
// Textures
//--------------------------------------------------------------------------------------
texture2D texColor;
texture2D texDepth;
texture2D texNoise;
texture2D texPalette;
texture2D texFocus; //computed focusing depth
texture2D texCurr; //4*4 texture for focusing
texture2D texPrev; //4*4 texture for focusing
//--------------------------------------------------------------------------------------
// Sampler Inputs
//--------------------------------------------------------------------------------------


sampler2D InputSampler = sampler_state
{
    Texture = (texColor);
    MinFilter = POINT;
    MagFilter = POINT;
    MipFilter = POINT;
    AddressU   = Clamp;
	AddressV   = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

sampler2D SamplerDepth = sampler_state
{
	Texture   = <texDepth>;
	MinFilter = POINT;
	MagFilter = POINT;
	MipFilter = NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

sampler2D SamplerNoise = sampler_state
{
	Texture   = <texNoise>;
	MinFilter = POINT;
	MagFilter = POINT;
	MipFilter = NONE;//NONE;
	AddressU  = Wrap;
	AddressV  = Wrap;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

sampler2D SamplerPalette = sampler_state
{
	Texture   = <texPalette>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;//NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

//for focus computation
sampler2D SamplerCurr = sampler_state
{
	Texture   = <texCurr>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;//NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

//for focus computation
sampler2D SamplerPrev = sampler_state
{
	Texture   = <texPrev>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};
//for dof only in PostProcess techniques
sampler2D SamplerFocus = sampler_state
{
	Texture   = <texFocus>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

struct VS_OUTPUT_POST
{
	float4 vpos  : POSITION;
	float2 txcoord : TEXCOORD0;
};

struct VS_INPUT_POST
{
	float3 pos  : POSITION;
	float2 txcoord : TEXCOORD0;
};


#ifdef ADOF
////////////////////////////////////////////////////////////////////
//begin focusing code
////////////////////////////////////////////////////////////////////
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
VS_OUTPUT_POST VS_Focus(VS_INPUT_POST IN)
{
	VS_OUTPUT_POST OUT;

	float4 pos=float4(IN.pos.x,IN.pos.y,IN.pos.z,1.0);

	OUT.vpos=pos;
	OUT.txcoord.xy=IN.txcoord.xy;

	return OUT;
}

float linearlizeDepth(float nonlinearDepth)
{
	float2 dofProj=float2(DOFDepthLine, 3098.0392);
	float2 dofDist=float2(1.83, 0.0);
		
	float4 depth=nonlinearDepth;
	
	
	depth.y=-dofProj.x + dofProj.y;
	depth.y=1.0/depth.y;
	depth.z=depth.y * dofProj.y; 
	depth.z=depth.z * -dofProj.x; 
	depth.x=dofProj.y * -depth.y + depth.x;
	depth.x=1.0/depth.x;

	depth.y=depth.z * depth.x;

	depth.x=depth.z * depth.x - dofDist.y; 
	depth.x+=dofDist.x * -0.5;

	depth.x=max(depth.x, 0.0);
		
	return depth.x;
}


//SRCpass1X=ScreenWidth;
//SRCpass1Y=ScreenHeight;
//DESTpass2X=4;
//DESTpass2Y=4;
float4 PS_ReadFocus(VS_OUTPUT_POST IN) : COLOR
{

	float2 uvsrc=FocusPoint;

	float2 pixelSize=ScreenSize.y;
	pixelSize.y*=ScreenSize.z;
	
	const float2 offset[4]=
	{
		float2(0.0, 1.0),
		float2(0.0, -1.0),
		float2(1.0, 0.0),
		float2(-1.0, 0.0)
	};

	float res=linearlizeDepth(tex2D(SamplerDepth, uvsrc.xy).x);
	for (int i=0; i<4; i++)
	{
		uvsrc.xy=uvsrc.xy;
		uvsrc.xy+=offset[i] * pixelSize.xy * FocusSampleRange;
		#ifdef NOT_BLURRING_SKY_MODE
			res+=linearlizeDepth(tex2D(SamplerDepth, uvsrc).x);
		#else
			res+=min(linearlizeDepth(tex2D(SamplerDepth, uvsrc).x), DepthClip);
		#endif
	}
	res*=0.2;


	

	return res;
}



//SRCpass1X=4;
//SRCpass1Y=4;
//DESTpass2X=4;
//DESTpass2Y=4;
float4 PS_WriteFocus(VS_OUTPUT_POST IN) : COLOR
{

	float2 uvsrc=FocusPoint;

	float res=0.0;
	float curr=tex2D(SamplerCurr, uvsrc.xy).x;
	float prev=tex2D(SamplerPrev, uvsrc.xy).x;

	
	res=lerp(prev, curr, saturate(FadeFactor));//time elapsed factor

	return res;
}



//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


technique ReadFocus
{
	pass P0
	{
		VertexShader = compile vs_3_0 VS_Focus();
		PixelShader  = compile ps_3_0 PS_ReadFocus();

		ZEnable=FALSE;
		CullMode=NONE;
		ALPHATESTENABLE=FALSE;
		SEPARATEALPHABLENDENABLE=FALSE;
		AlphaBlendEnable=FALSE;
		FogEnable=FALSE;
		SRGBWRITEENABLE=FALSE;
	}
}



technique WriteFocus
{
	pass P0
	{
		VertexShader = compile vs_3_0 VS_Focus();
		PixelShader  = compile ps_3_0 PS_WriteFocus();

		ZEnable=FALSE;
		CullMode=NONE;
		ALPHATESTENABLE=FALSE;
		SEPARATEALPHABLENDENABLE=FALSE;
		AlphaBlendEnable=FALSE;
		FogEnable=FALSE;
		SRGBWRITEENABLE=FALSE;
	}
}


////////////////////////////////////////////////////////////////////
//end focusing code
////////////////////////////////////////////////////////////////////


#endif




//--------------------------------------------------------------------------------------
// Vertex Shader Input
//--------------------------------------------------------------------------------------

VS_OUTPUT_POST VS_PostProcess(VS_INPUT_POST IN)
{
	VS_OUTPUT_POST OUT;

	float4 pos=float4(IN.pos.x,IN.pos.y,IN.pos.z,1.0);

	OUT.vpos=pos;
	OUT.txcoord.xy=IN.txcoord.xy;

	return OUT;
}

//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------


float Luminance( float3 c )
{
	return dot( c, float3(0.22, 0.707, 0.071) );
}



#ifdef NOISE

float Random(float2 co)
{
    return frac(sin(dot(co.xy, float2(12.9898, 78.233))) * 43758.5453);
}

float Grain(float3 tex)
{
	float PI = 3.1415926535897932384626433832795;
	float rofl = Random(tex.xy);
	float grain = sin(PI * tex.z * rofl * fGrainFreq) * fGrainScale * rofl;
	return grain;
}
#endif


float4 main(VS_OUTPUT_POST i, float2 vPos : VPOS) : COLOR
{
    float4 color = tex2D(InputSampler, i.txcoord);

#ifdef HSVULTIMATE
#ifdef ENABLE_HSV_CONVERSION
float3 hsvcolor = RGBtoHSV( color.xyz );

#ifdef ENABLE_POW_CURVE
#ifdef ENABLE_HUE_ADJUSTMENT
hsvcolor.x = EColorHueMod + ( EColorHueMult * pow( hsvcolor.x, EColorHuePow ) );
#endif
#ifdef ENABLE_SATURATION_ADJUSTMENT
hsvcolor.y = EColorSaturationMod + ( EColorSaturationMult * pow( hsvcolor.y, EColorSaturationPow ) );
#endif
#ifdef ENABLE_INTENSITY_ADJUSTMENT
hsvcolor.z = EColorIntensityMod + ( EColorIntensityMult * pow( hsvcolor.z, EColorIntensityPow ) );
#endif
#ifdef ENABLE_COLOR_EQUALIZER
hsvcolor.y = ColorEqualizerMod( hsvcolor.x ) + ( ColorEqualizerMult( hsvcolor.x ) * pow( hsvcolor.y, ColorEqualizerPow( hsvcolor.x ) ) );
#endif
#endif

#ifndef ENABLE_POW_CURVE
#ifdef ENABLE_HUE_ADJUSTMENT
hsvcolor.x = EColorHueMod + ( EColorHueMult * hsvcolor.x );
#endif
#ifdef ENABLE_SATURATION_ADJUSTMENT
hsvcolor.y = EColorSaturationMod + ( EColorSaturationMult * hsvcolor.y );
#endif
#ifdef ENABLE_INTENSITY_ADJUSTMENT
hsvcolor.z = EColorIntensityMod + ( EColorIntensityMult * hsvcolor.z );
#endif
#ifdef ENABLE_COLOR_EQUALIZER
hsvcolor.y = ColorEqualizerMod( hsvcolor.x ) + ( ColorEqualizerMult( hsvcolor.x ) * hsvcolor.y );
#endif
#endif

hsvcolor.y = max( hsvcolor.y, 0.0 );
hsvcolor.z = max( hsvcolor.z, 0.0 );
color.xyz = HSVtoRGB( hsvcolor );
#endif
#endif


#ifdef GAMMACORRECTION
color = pow(color, 1/GammaAmount);
#endif

#ifdef COLORCORRMAIN
color.r = (color.r)*(0.05 + 1.0f) + (color.g + color.b)*(-0.04); 
color.g = (color.g)*(0.06 + 1.0f) + (color.r + color.b)*(-0.04);
color.b = (color.b)*(0.055 + 1.0f) + (color.r + color.g)*(-0.04);

color.rgb = (color.rgb * (1.0 + color.rgb / 2))/(color.rgb + 4);
color = color*(1.0f + 0.2) - 0.12;
#endif


#ifdef COLORCORRMAIN
color = saturate(color);
color = 1 - (0.97 - 0.065)*(1.04 - color);
color = saturate(color);
color = color + (0.82f / 2.0 - 0.5) * (1.0 - color);
color = saturate(color);
color.rgb = pow(0.85f * color, 1.0 / 0.95f); 

float dbr = -color.r + 1.4f;
float dbg = -color.g + 1.4f;
float dbb = -color.b + 1.4f;

float pr = lerp(dbr, 0.55f, 0.66f);
float pg = lerp(dbg, 0.55f, 0.66f);
float pb = lerp(dbb, 0.55f, 0.66f);

color.r = pow((color.r * 0.94f - 0.0035f), pr);
color.g = pow((color.g * 0.94f - 0.002f), pg);
color.b = pow((color.b * 0.91f + 0.001f), pb);

color = color * 4.0;
#endif

#ifdef FILMICCURVE
float3 curr = Uncharted2Tonemap(color);
float3 whiteScale = Uncharted2Tonemap(FilmWeight);
color.xyz = curr*whiteScale;
color = pow(color, 0.55);
color = color*FilmicExposure;
#endif

#ifdef REINHARD_ICE21
float pixelLumi = dot(color.xyz, LUM_FACTOR.xyz);
float toneMapCalc = pixelLumi / (pixelLumi + 1);
color =  toneMapCalc * pow(color / pixelLumi, REINHARD_SAT);
color = color * TONEMAPEXP;
#endif

float toneMapExposure = 1.2;

color = color * toneMapExposure;
color = max(0, color - 0.004);
color = (color * (6.2 * color + 0.5)) / (color * (6.2 * color + 1.7)+ 0.06);
color = pow(color, 2.2);


#ifdef CROSSPROCESS

		float4 image1 = color;
		float4 image2 = color;
		float gray = dot(float3(0.5,0.5,0.5), image1);

		image1 = lerp (gray, image1,CrossSaturation2);

		image1 = lerp (0.35, image1,CrossContrast);

		image1 +=CrossBrightness;
		image1 *=1.2;

		image2.r = image1.r * crossMatrix[0].x + crossMatrix[0].y;
		image2.g = image1.g * crossMatrix[1].x + crossMatrix[1].y;
		image2.b = image1.b * crossMatrix[2].x + crossMatrix[2].y;

		color = lerp(image1, image2, CrossAmount);

#endif

#ifdef CROSSICE
float Weight;
float4 colInput = color;
float4 colMood = 1.0f;
colMood.r = moodR;
colMood.g = moodG;
colMood.b = moodB;
float fLum = ( colInput.r + colInput.g + colInput.b ) / 3;
colMood = lerp(0, colMood, saturate(fLum * 2.0));
colMood = lerp(colMood, 1, saturate(fLum - 0.5) * 2.0);
float4 colOutput = lerp(colInput, colMood, saturate(fLum * fRatio));
color.rgb=max(0, colOutput);
#endif

#ifdef HDR
color.xyz = max(0, color.xyz - Defog * FogColor.xyz);
color.xyz *= pow(2.0f, Exposure);
color.xyz = pow(color.xyz, Gamma);
float3 trollface = color.xyz * float3(1.05f, 0.97f, 1.27f);
color.xyz = lerp(color.xyz, trollface, BlueShift);
#endif

#ifdef FILMICPASS
color = FilmPass(color);
#endif

#ifdef VIBRANCEPASS
float3 lumCoeff = float3(0.2126, 0.7152, 0.0722);
float vibranceluma = dot(lumCoeff, color.xyz);

float max_color = max(color.x, max(color.y,color.z)); //Find the strongest color
float min_color = min(color.x, max(color.y,color.z)); //Find the weakest color
float color_saturation = max_color - min_color;

color.xyz = lerp(vibranceluma, color.xyz, (1.0 + (Vibrance * (1.0 - (sign(Vibrance) * color_saturation)))));
#endif


#ifdef COLORWASHOUT
float	colorGray=dot(color.xyz, 0.333);
float	colorGray2=(colorGray*(6.2*colorGray+0.5))/(colorGray*(6.2*colorGray+1.7)+0.06);
float	colorGray3=pow(colorGray, 0.36);
float	colorWashout=saturate(colorGray2 - ColorWashoutThreshold)/(1.00 - ColorWashoutThreshold);
colorWashout=saturate(pow(colorWashout, ColorWashoutPow) * ColorWashoutAmount);

float3	middleColor=(color.xyz+0.0001)/(colorGray+0.000001);
middleColor.xyz=lerp(pow(middleColor.xyz, ColorSaturation), middleColor.xyz, ColorSaturation);
middleColor.xyz=lerp(middleColor.xyz, 1.00, saturate(colorWashout*ColorWashoutAmount));
float tonemapMix=(0.5 - ColorDullnessAmount)*0.60; //temp
	colorGray=lerp(colorGray2, colorGray3, tonemapMix);
	color.xyz=middleColor.xyz*colorGray;
color.xyz *= ExpAdjustment;
#endif



#ifdef BORISVIGNETTE
	float2	uv=(i.txcoord-0.5)*EVignetteRadius;
	float	vignetteold=saturate(dot(uv.xy, uv.xy));
	vignetteold=pow(vignetteold, EVignetteCurve);
	#ifdef VIGNCOLORING
	float3	EVignetteColor=float3(VIGNREDAMOUNT, VIGNGREENAMOUNT, VIGNBLUEAMOUNT);
	#else
	float3	EVignetteColor=float3(0.0, 0.0, 0.0);
	#endif
	color.xyz=lerp(color.xyz, EVignetteColor, vignetteold*EVignetteAmount);
#endif

#ifdef HD6_VIGNETTE

	float rovigpwr = CircularPower; //for a circular vignette
	float2 sqvigpwr = float2( SquareTop, SquareBottom ); // for the top and bottom of the screen
	float vsatstrength = ColorDistortion; // color distortion
	float vignettepow = ContrastSharpen; // increases the contrast and sharpness
	float vstrengthatnight = VignetteBorder;
 
 	float2 inTex = i.txcoord;
 	float vhnd = 0.5;
 	float4 voriginal = color;
 	float4 vcolor = voriginal;
 	vcolor.xyz=1;
 	inTex -= 0.5; // center
 	inTex.y += 0.01; // offset from the center
 	float vignette = 1.0 - dot( inTex, inTex );
 	vcolor *= pow( vignette, vignettepow );
 
 	float4 rvigtex = vcolor;
 	rvigtex.xyz = pow( vcolor, 1 );
 	rvigtex.xyz = lerp(float3(0.5, 0.5, 0.5), rvigtex.xyz, 2.25); // contrast
 	rvigtex.xyz = lerp(float3(1,1,1),rvigtex.xyz,rovigpwr); // strength of the circular vinetty
 
//darken the top and bottom
 	float4 vigtex = vcolor;
 	vcolor.xyz = float3(1,1,1);

#ifdef LEFTANDRIGHT
 	float3 topv = min((inTex.x+0.5)*2,1.5) * 2; // top
 	float3 botv = min(((0-inTex.x)+0.5)*2,1.5) * 2; // botton
	topv= lerp(float3(1,1,1), topv, sqvigpwr.x);
 	botv= lerp(float3(1,1,1), botv, sqvigpwr.y);
	vigtex.xyz = (topv)*(botv);
#endif
#ifdef TOPANDBOTTOM
        float3 topv = min((inTex.y+0.5)*2,1.5) * 2; // top
 	float3 botv = min(((0-inTex.y)+0.5)*2,1.5) * 2; // botton
	topv= lerp(float3(1,1,1), topv, sqvigpwr.x);
 	botv= lerp(float3(1,1,1), botv, sqvigpwr.y);
	vigtex.xyz = (topv)*(botv);
#endif
#ifdef CORNERDARKEN
	float3 rightv = min((inTex.x+0.5)*2,1.5) * 2;
 	float3 leftv = min(((0-inTex.x)+0.5)*2,1.5) * 2; 
        float3 topv = min((inTex.y+0.5)*2,1.5) * 2; 
 	float3 botv = min(((0-inTex.y)+0.5)*2,1.5) * 2; 
 	rightv= lerp(float3(1,1,1), rightv, sqvigpwr.y);
 	leftv= lerp(float3(1,1,1), leftv, sqvigpwr.x);
        topv= lerp(float3(1,1,1), topv, sqvigpwr.x);
 	botv= lerp(float3(1,1,1), botv, sqvigpwr.y);
 	vigtex.xyz = (topv)*(botv)*(rightv)*(leftv);
#endif
 	
 	
 	//vigtex.xyz = lerp(float3(1,1,1),vigtex.xyz,sqvigpwr); // strength of the top and bottom
 
 // mix the two types of vignettes
 	vigtex.xyz*=rvigtex.xyz;
	vigtex.xyz = lerp(vigtex.xyz,float3(1,1,1),(vhnd-vstrengthatnight*vhnd)); //for a dark screen
 	vigtex.xyz = min(vigtex.xyz,1);
 	vigtex.xyz = max(vigtex.xyz,0);
 	float3 vtintensity = dot(voriginal.xyz, float3(0.2125, 0.7154, 0.0721));
 	color.xyz = lerp(vtintensity, voriginal.xyz, ((((1-(vigtex.xyz*2))+2)-1)*vsatstrength)+1 );
  	color.xyz *= (vigtex.xyz);
#endif

float2 InputSize = float2(sxres, syres/aspect);
float Amount = sharps;
float2 offset = offsetv / InputSize;
float4 sharpencolor=tex2D(InputSampler, i.txcoord);
sharpencolor += tex2D(InputSampler, i.txcoord - offset) * Amount;
sharpencolor -= tex2D(InputSampler, i.txcoord + offset) * Amount;

 
#ifdef USE_DITHER2
float dither_size = 2.0;  //move to settings?
float dither_bit  = 8.0;  //move to settings?
float grid_position = frac(dot(i.txcoord,(screen_size / dither_size)) + (0.5 / dither_size)); 
float dither_shift = (0.25) * (1.0 / (pow(2,dither_bit) - 1.0));
color.xyz += lerp(2.0 * dither_shift,(-2.0 * dither_shift),grid_position); 
#endif

#ifdef USE_DITHER
float dither_size = 2.0;  //move to settings?
float dither_bit  = 8.0;  //move to settings?
float grid_position = frac(dot(i.txcoord,(screen_size / dither_size)) + (0.5 / dither_size)); 
float dither_shift = (0.25) * (1.0 / (pow(2,dither_bit) - 1.0));
float3 dither_shift_RGB = float3(dither_shift, dither_shift, dither_shift);
color.xyz += lerp(2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position); 
#endif

color.w = 1.0;

return color*sharpencolor;
}

#ifdef LIGHTSCATTERING
float4 PS_ProcessSunShafts(VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR 
{	
	float2 texCoord = IN.txcoord;
	// Calculate vector from pixel to light source in screen space.  
    half2 deltaTexCoord = (texCoord - ScreenLightPos.xy);  
    // Divide by number of samples and scale by control factor.  
    deltaTexCoord *= 1.0f / NUM_SAMPLES * Density;  
    // Store initial sample.  
    half3 color = max(float4(0,0,0,0),tex2D(InputSampler, texCoord)-SStresh);  
	// Set up illumination decay factor.  
	half illuminationDecay = 1.0f;  
	// Evaluate summation from Equation 3 NUM_SAMPLES iterations.  
	for (int i = 0; i < NUM_SAMPLES; i++)  
	{  
		// Step sample location along ray.  
		texCoord -= deltaTexCoord;  
		// Retrieve sample at new location.  
	    half3 sample = max(float4(0,0,0,0),tex2D(InputSampler, texCoord)-SStresh);  
		// Apply sample attenuation scale/decay factors.  

#ifdef TINTCOLOR
                sample.r *= REDAMOUNT;
		sample.g *= GREENAMOUNT;
		sample.b *= BLUEAMOUNT;
#endif

#ifdef COLORING
sample = dot(sample, float3(0.3, 0.59, 0.11));
                sample.r *= REDAMOUNT;
		sample.g *= GREENAMOUNT;
		sample.b *= BLUEAMOUNT;
#endif

		sample *= illuminationDecay * Weight;  
		// Accumulate combined color.  
		color += sample;  
		// Update exponential decay factor.  
		illuminationDecay *= Decay;  
	}
	// Output final color with a further scale control factor.  
	return float4( saturate(color*SunExposure) , color.x);
}
#endif



float4 CBloom (VS_OUTPUT_POST i, float2 vPos : VPOS) : COLOR
{

float4 BloomThreshold = {fBloomThreshold, 1/(1-fBloomThreshold), 5.0, 5.0};

float4 tcol = tex2D(InputSampler, i.txcoord);
float4 bloomsample = float4(0,0,0,0);

#ifdef COLORMODBLOOM
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x, i.txcoord.y,0,BloomDownsampling)) * 0.19741;

    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.94201624*BloomRadius, i.txcoord.y- 0.39906216*BloomRadius,0,BloomDownsampling)) * 0.19741;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.94558609*BloomRadius, i.txcoord.y- 0.76890725*BloomRadius,0,BloomDownsampling)) * 0.19741;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.09418410*BloomRadius, i.txcoord.y- 0.92938870*BloomRadius,0,BloomDownsampling)) * 0.19741;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.34495938*BloomRadius, i.txcoord.y+ 0.29387760*BloomRadius,0,BloomDownsampling)) * 0.19741; 
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.91588581*BloomRadius, i.txcoord.y+ 0.45771432*BloomRadius,0,BloomDownsampling)) * 0.19741;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.81544232*BloomRadius, i.txcoord.y- 0.87912464*BloomRadius,0,BloomDownsampling)) * 0.19741;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.38277543*BloomRadius, i.txcoord.y+ 0.27676845*BloomRadius,0,BloomDownsampling)) * 0.19741;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.97484398*BloomRadius, i.txcoord.y+ 0.75648379*BloomRadius,0,BloomDownsampling)) * 0.19741;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.44323325*BloomRadius, i.txcoord.y- 0.97511554*BloomRadius,0,BloomDownsampling)) * 0.19741;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.53742981*BloomRadius, i.txcoord.y- 0.47373420*BloomRadius,0,BloomDownsampling)) * 0.19741;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.26496911*BloomRadius, i.txcoord.y- 0.41893023*BloomRadius,0,BloomDownsampling)) * 0.19741;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.79197514*BloomRadius, i.txcoord.y+ 0.19090188*BloomRadius,0,BloomDownsampling)) * 0.19741;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.24188840*BloomRadius, i.txcoord.y+ 0.99706507*BloomRadius,0,BloomDownsampling)) * 0.19741;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.81409955*BloomRadius, i.txcoord.y+ 0.91437590*BloomRadius,0,BloomDownsampling)) * 0.19741;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.19984126*BloomRadius, i.txcoord.y+ 0.78641367*BloomRadius,0,BloomDownsampling)) * 0.19741;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.14383161*BloomRadius, i.txcoord.y- 0.14100790*BloomRadius,0,BloomDownsampling)) * 0.19741;


    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.94201624*BloomRadius*1.5, i.txcoord.y- 0.39906216*BloomRadius*1.5,0,BloomDownsampling)) * 0.17467;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.94558609*BloomRadius*1.5, i.txcoord.y- 0.76890725*BloomRadius*1.5,0,BloomDownsampling)) * 0.17467;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.09418410*BloomRadius*1.5, i.txcoord.y- 0.92938870*BloomRadius*1.5,0,BloomDownsampling)) * 0.17467;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.34495938*BloomRadius*1.5, i.txcoord.y+ 0.29387760*BloomRadius*1.5,0,BloomDownsampling)) * 0.17467; 
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.91588581*BloomRadius*1.5, i.txcoord.y+ 0.45771432*BloomRadius*1.5,0,BloomDownsampling)) * 0.17467;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.81544232*BloomRadius*1.5, i.txcoord.y- 0.87912464*BloomRadius*1.5,0,BloomDownsampling)) * 0.17467;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.38277543*BloomRadius*1.5, i.txcoord.y+ 0.27676845*BloomRadius*1.5,0,BloomDownsampling)) * 0.17467;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.97484398*BloomRadius*1.5, i.txcoord.y+ 0.75648379*BloomRadius*1.5,0,BloomDownsampling)) * 0.17467;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.44323325*BloomRadius*1.5, i.txcoord.y- 0.97511554*BloomRadius*1.5,0,BloomDownsampling)) * 0.17467;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.53742981*BloomRadius*1.5, i.txcoord.y- 0.47373420*BloomRadius*1.5,0,BloomDownsampling)) * 0.17467;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.26496911*BloomRadius*1.5, i.txcoord.y- 0.41893023*BloomRadius*1.5,0,BloomDownsampling)) * 0.17467;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.79197514*BloomRadius*1.5, i.txcoord.y+ 0.19090188*BloomRadius*1.5,0,BloomDownsampling)) * 0.17467;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.24188840*BloomRadius*1.5, i.txcoord.y+ 0.99706507*BloomRadius*1.5,0,BloomDownsampling)) * 0.17467;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.81409955*BloomRadius*1.5, i.txcoord.y+ 0.91437590*BloomRadius*1.5,0,BloomDownsampling)) * 0.17467;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.19984126*BloomRadius*1.5, i.txcoord.y+ 0.78641367*BloomRadius*1.5,0,BloomDownsampling)) * 0.17467;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.14383161*BloomRadius*1.5, i.txcoord.y- 0.14100790*BloomRadius*1.5,0,BloomDownsampling)) * 0.17467;


    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.94201624*BloomRadius*2.0, i.txcoord.y- 0.39906216*BloomRadius*2.0,0,BloomDownsampling)) * 0.12098;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.94558609*BloomRadius*2.0, i.txcoord.y- 0.76890725*BloomRadius*2.0,0,BloomDownsampling)) * 0.12098;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.09418410*BloomRadius*2.0, i.txcoord.y- 0.92938870*BloomRadius*2.0,0,BloomDownsampling)) * 0.12098;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.34495938*BloomRadius*2.0, i.txcoord.y+ 0.29387760*BloomRadius*2.0,0,BloomDownsampling)) * 0.12098;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.91588581*BloomRadius*2.0, i.txcoord.y+ 0.45771432*BloomRadius*2.0,0,BloomDownsampling)) * 0.12098;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.81544232*BloomRadius*2.0, i.txcoord.y- 0.87912464*BloomRadius*2.0,0,BloomDownsampling)) * 0.12098;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.38277543*BloomRadius*2.0, i.txcoord.y+ 0.27676845*BloomRadius*2.0,0,BloomDownsampling)) * 0.12098;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.97484398*BloomRadius*2.0, i.txcoord.y+ 0.75648379*BloomRadius*2.0,0,BloomDownsampling)) * 0.12098;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.44323325*BloomRadius*2.0, i.txcoord.y- 0.97511554*BloomRadius*2.0,0,BloomDownsampling)) * 0.12098;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.53742981*BloomRadius*2.0, i.txcoord.y- 0.47373420*BloomRadius*2.0,0,BloomDownsampling)) * 0.12098;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.26496911*BloomRadius*2.0, i.txcoord.y- 0.41893023*BloomRadius*2.0,0,BloomDownsampling)) * 0.12098;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.79197514*BloomRadius*2.0, i.txcoord.y+ 0.19090188*BloomRadius*2.0,0,BloomDownsampling)) * 0.12098;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.24188840*BloomRadius*2.0, i.txcoord.y+ 0.99706507*BloomRadius*2.0,0,BloomDownsampling)) * 0.12098;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.81409955*BloomRadius*2.0, i.txcoord.y+ 0.91437590*BloomRadius*2.0,0,BloomDownsampling)) * 0.12098;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.19984126*BloomRadius*2.0, i.txcoord.y+ 0.78641367*BloomRadius*2.0,0,BloomDownsampling)) * 0.12098;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.14383161*BloomRadius*2.0, i.txcoord.y- 0.14100790*BloomRadius*2.0,0,BloomDownsampling)) * 0.12098;



    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.94201624*BloomRadius*2.5, i.txcoord.y- 0.39906216*BloomRadius*2.5,0,BloomDownsampling)) * 0.06559;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.94558609*BloomRadius*2.5, i.txcoord.y- 0.76890725*BloomRadius*2.5,0,BloomDownsampling)) * 0.06559;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.09418410*BloomRadius*2.5, i.txcoord.y- 0.92938870*BloomRadius*2.5,0,BloomDownsampling)) * 0.06559;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.34495938*BloomRadius*2.5, i.txcoord.y+ 0.29387760*BloomRadius*2.5,0,BloomDownsampling)) * 0.06559;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.91588581*BloomRadius*2.5, i.txcoord.y+ 0.45771432*BloomRadius*2.5,0,BloomDownsampling)) * 0.06559;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.81544232*BloomRadius*2.5, i.txcoord.y- 0.87912464*BloomRadius*2.5,0,BloomDownsampling)) * 0.06559;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.38277543*BloomRadius*2.5, i.txcoord.y+ 0.27676845*BloomRadius*2.5,0,BloomDownsampling)) * 0.06559;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.97484398*BloomRadius*2.5, i.txcoord.y+ 0.75648379*BloomRadius*2.5,0,BloomDownsampling)) * 0.06559;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.44323325*BloomRadius*2.5, i.txcoord.y- 0.97511554*BloomRadius*2.5,0,BloomDownsampling)) * 0.06559;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.53742981*BloomRadius*2.5, i.txcoord.y- 0.47373420*BloomRadius*2.5,0,BloomDownsampling)) * 0.06559;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.26496911*BloomRadius*2.5, i.txcoord.y- 0.41893023*BloomRadius*2.5,0,BloomDownsampling)) * 0.06559;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.79197514*BloomRadius*2.5, i.txcoord.y+ 0.19090188*BloomRadius*2.5,0,BloomDownsampling)) * 0.06559;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.24188840*BloomRadius*2.5, i.txcoord.y+ 0.99706507*BloomRadius*2.5,0,BloomDownsampling)) * 0.06559;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.81409955*BloomRadius*2.5, i.txcoord.y+ 0.91437590*BloomRadius*2.5,0,BloomDownsampling)) * 0.06559;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.19984126*BloomRadius*2.5, i.txcoord.y+ 0.78641367*BloomRadius*2.5,0,BloomDownsampling)) * 0.06559;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.14383161*BloomRadius*2.5, i.txcoord.y- 0.14100790*BloomRadius*2.5,0,BloomDownsampling)) * 0.06559;


    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.94201624*BloomRadius*3.0, i.txcoord.y- 0.39906216*BloomRadius*3.0,0,BloomDownsampling)) * 0.02783;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.94558609*BloomRadius*3.0, i.txcoord.y- 0.76890725*BloomRadius*3.0,0,BloomDownsampling)) * 0.02783;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.09418410*BloomRadius*3.0, i.txcoord.y- 0.92938870*BloomRadius*3.0,0,BloomDownsampling)) * 0.02783;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.34495938*BloomRadius*3.0, i.txcoord.y+ 0.29387760*BloomRadius*3.0,0,BloomDownsampling)) * 0.02783;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.91588581*BloomRadius*3.0, i.txcoord.y+ 0.45771432*BloomRadius*3.0,0,BloomDownsampling)) * 0.02783;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.81544232*BloomRadius*3.0, i.txcoord.y- 0.87912464*BloomRadius*3.0,0,BloomDownsampling)) * 0.02783;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.38277543*BloomRadius*3.0, i.txcoord.y+ 0.27676845*BloomRadius*3.0,0,BloomDownsampling)) * 0.02783;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.97484398*BloomRadius*3.0, i.txcoord.y+ 0.75648379*BloomRadius*3.0,0,BloomDownsampling)) * 0.02783;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.44323325*BloomRadius*3.0, i.txcoord.y- 0.97511554*BloomRadius*3.0,0,BloomDownsampling)) * 0.02783;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.53742981*BloomRadius*3.0, i.txcoord.y- 0.47373420*BloomRadius*3.0,0,BloomDownsampling)) * 0.02783;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.26496911*BloomRadius*3.0, i.txcoord.y- 0.41893023*BloomRadius*3.0,0,BloomDownsampling)) * 0.02783;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.79197514*BloomRadius*3.0, i.txcoord.y+ 0.19090188*BloomRadius*3.0,0,BloomDownsampling)) * 0.02783;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.24188840*BloomRadius*3.0, i.txcoord.y+ 0.99706507*BloomRadius*3.0,0,BloomDownsampling)) * 0.02783;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.81409955*BloomRadius*3.0, i.txcoord.y+ 0.91437590*BloomRadius*3.0,0,BloomDownsampling)) * 0.02783;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.19984126*BloomRadius*3.0, i.txcoord.y+ 0.78641367*BloomRadius*3.0,0,BloomDownsampling)) * 0.02783;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.14383161*BloomRadius*3.0, i.txcoord.y- 0.14100790*BloomRadius*3.0,0,BloomDownsampling)) * 0.02783;


    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.94201624*BloomRadius*3.5, i.txcoord.y- 0.39906216*BloomRadius*3.5,0,BloomDownsampling)) * 0.01222;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.94558609*BloomRadius*3.5, i.txcoord.y- 0.76890725*BloomRadius*3.5,0,BloomDownsampling)) * 0.01222;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.09418410*BloomRadius*3.5, i.txcoord.y- 0.92938870*BloomRadius*3.5,0,BloomDownsampling)) * 0.01222;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.34495938*BloomRadius*3.5, i.txcoord.y+ 0.29387760*BloomRadius*3.5,0,BloomDownsampling)) * 0.01222;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.91588581*BloomRadius*3.5, i.txcoord.y+ 0.45771432*BloomRadius*3.5,0,BloomDownsampling)) * 0.01222;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.81544232*BloomRadius*3.5, i.txcoord.y- 0.87912464*BloomRadius*3.5,0,BloomDownsampling)) * 0.01222;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.38277543*BloomRadius*3.5, i.txcoord.y+ 0.27676845*BloomRadius*3.5,0,BloomDownsampling)) * 0.01222;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.97484398*BloomRadius*3.5, i.txcoord.y+ 0.75648379*BloomRadius*3.5,0,BloomDownsampling)) * 0.01222;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.44323325*BloomRadius*3.5, i.txcoord.y- 0.97511554*BloomRadius*3.5,0,BloomDownsampling)) * 0.01222;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.53742981*BloomRadius*3.5, i.txcoord.y- 0.47373420*BloomRadius*3.5,0,BloomDownsampling)) * 0.01222;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.26496911*BloomRadius*3.5, i.txcoord.y- 0.41893023*BloomRadius*3.5,0,BloomDownsampling)) * 0.01222;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.79197514*BloomRadius*3.5, i.txcoord.y+ 0.19090188*BloomRadius*3.5,0,BloomDownsampling)) * 0.01222;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.24188840*BloomRadius*3.5, i.txcoord.y+ 0.99706507*BloomRadius*3.5,0,BloomDownsampling)) * 0.01222;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x - 0.81409955*BloomRadius*3.5, i.txcoord.y+ 0.91437590*BloomRadius*3.5,0,BloomDownsampling)) * 0.01222;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.19984126*BloomRadius*3.5, i.txcoord.y+ 0.78641367*BloomRadius*3.5,0,BloomDownsampling)) * 0.01222;
    bloomsample += tex2Dlod(InputSampler, float4(i.txcoord.x + 0.14383161*BloomRadius*3.5, i.txcoord.y- 0.14100790*BloomRadius*3.5,0,BloomDownsampling)) * 0.01222;

#endif


#ifndef COLORBLOOM
bloomsample = dot(bloomsample, float3(0.3, 0.59, 0.11));
#endif


bloomsample = bloomsample * BloomCurve;

bloomsample =max(1.0,0.0);

float4 tcol2 = max(float4(0.0,0.0,0.0,0.0), bloomsample-BloomThreshold.x);
float4 toBlend = saturate (tcol2 * fBloomIntensity);

float4 smpl = 1-(1-tcol)*(1-toBlend);

float4 Color;
Color = smpl;
return Color;
}




#ifdef CHROMATICABBERATION
float4 PS_PostProcessChroma(VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{

float4 coord=0.0;

coord.xy=IN.txcoord.xy;
coord.w=0.0;

float3 eta = float3(1.0+ChromaticAmount*0.9,1.0+ChromaticAmount*0.6,1.0+ChromaticAmount*0.3);
float2 center;
center.x = coord.x-0.5;
center.y = coord.y-0.5;
float LensZoom = 1.0/LensSize;

float r2 = (IN.txcoord.x-0.5) * (IN.txcoord.x-0.5) + (IN.txcoord.y-0.5) * (IN.txcoord.y-0.5);     
float f = 0;

if( LensDistortionCubic == 0.0){
	f = 1 + r2 * LensDistortion;
}else{
                f = 1 + r2 * (LensDistortion + LensDistortionCubic * sqrt(r2));
};

float x = f*LensZoom*(coord.x-0.5)+0.5;
float y = f*LensZoom*(coord.y-0.5)+0.5;
float2 rCoords = (f*eta.r)*LensZoom*(center.xy*0.5)+0.5;
float2 gCoords = (f*eta.g)*LensZoom*(center.xy*0.5)+0.5;
float2 bCoords = (f*eta.b)*LensZoom*(center.xy*0.5)+0.5;

//float3 inputDistord = tex2D(InputSampler,float2(x,y));
float4 inputDistord = float4(tex2D(InputSampler,rCoords).r , tex2D(InputSampler,gCoords).g ,tex2D(InputSampler,bCoords).b, tex2D(InputSampler,float2(x,y)).a);
return float4(inputDistord.r,inputDistord.g,inputDistord.b,1);
}
#endif


#ifdef NOISE
float4 PS_ProcessPass_ImageGrain(VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{
	float4 res;
	float2 coord = IN.txcoord.xy;
	res.xyz = tex2D(InputSampler, coord.xy).xyz;
	res.xyz += tex2D(SamplerNoise, coord.xy * 1024).xyz * Grain(float3(coord.xy, SEED));
	res.a = 1.0;
	return res;
}
#endif

#ifdef MATSO_FLARE
float3 BrightPass(float2 tex)
{
    float3 couleur = tex2D(InputSampler, tex).rgb;
    float3 bC = max(couleur - float3(fFlareLuminance, fFlareLuminance, fFlareLuminance), 0.0);
    float bright = dot(bC, 1.0);
    bright = smoothstep(0.0f, 0.5, bright);
    return lerp(0.0, couleur, bright);
}


float3 AnamorphicSample(int axis, float2 tex, float blur)
{
	tex = 2.0 * tex - 1.0;
	if (!axis) tex.x /= -blur;
	else tex.y /= -blur;
	tex = 0.5 * tex + 0.5;
	return BrightPass(tex);
}


float4 PS_ProcessPass_Anamorphic(VS_OUTPUT_POST IN, float2 vPos : VPOS, uniform int axis) : COLOR
{
	float4 res;
	float2 coord = IN.txcoord.xy;
	

#ifdef fFlareHorizontal
	#define fFlareAxis	0
#endif
#ifdef fFlareVertical
	#define fFlareAxis	90
#endif
        
	float3 anamFlare = AnamorphicSample(axis, coord.xy, fFlareBlur) * fFlareTint;
#ifdef fFlareHorizontal
	anamFlare += AnamorphicSample(axis, coord.xy+float2(0, 4)*FlareRadius, fFlareBlur) * fFlareTint* 0.30;
	anamFlare += AnamorphicSample(axis, coord.xy+float2(0, 3)*FlareRadius, fFlareBlur) * fFlareTint* 0.54;
	anamFlare += AnamorphicSample(axis, coord.xy+float2(0, 2)*FlareRadius, fFlareBlur) * fFlareTint* 0.72;
	anamFlare += AnamorphicSample(axis, coord.xy+float2(0, 1)*FlareRadius, fFlareBlur) * fFlareTint* 0.90;
	anamFlare += AnamorphicSample(axis, coord.xy+float2(0, -1)*FlareRadius, fFlareBlur) * fFlareTint* 0.90;
	anamFlare += AnamorphicSample(axis, coord.xy+float2(0, -2)*FlareRadius, fFlareBlur) * fFlareTint* 0.72;
	anamFlare += AnamorphicSample(axis, coord.xy+float2(0, -3)*FlareRadius, fFlareBlur) * fFlareTint* 0.54;
	anamFlare += AnamorphicSample(axis, coord.xy+float2(0, -4)*FlareRadius, fFlareBlur) * fFlareTint* 0.30;
#endif
#ifdef fFlareVertical
        anamFlare += AnamorphicSample(axis, coord.xy+float2(4, 0)*FlareRadius, fFlareBlur) * fFlareTint* 0.30;
	anamFlare += AnamorphicSample(axis, coord.xy+float2(3, 0)*FlareRadius, fFlareBlur) * fFlareTint* 0.54;
	anamFlare += AnamorphicSample(axis, coord.xy+float2(2, 0)*FlareRadius, fFlareBlur) * fFlareTint* 0.72;
	anamFlare += AnamorphicSample(axis, coord.xy+float2(1, 0)*FlareRadius, fFlareBlur) * fFlareTint* 0.90;
	anamFlare += AnamorphicSample(axis, coord.xy+float2(1, 0)*FlareRadius, fFlareBlur) * fFlareTint* 0.90;
	anamFlare += AnamorphicSample(axis, coord.xy+float2(2, 0)*FlareRadius, fFlareBlur) * fFlareTint* 0.72;
	anamFlare += AnamorphicSample(axis, coord.xy+float2(3, 0)*FlareRadius, fFlareBlur) * fFlareTint* 0.54;
	anamFlare += AnamorphicSample(axis, coord.xy+float2(4, 0)*FlareRadius, fFlareBlur) * fFlareTint* 0.30;
#endif

	res.rgb = anamFlare * fFlareIntensity;
	res.a = 1.0;
	return res;
}
#endif



#ifdef ADOF

float4 PS_ProcessPass1(VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{
	float4 res;
	float2 coord=IN.txcoord.xy;

	float4 origcolor=tex2D(InputSampler, coord.xy);
	float scenedepth=tex2D(SamplerDepth, IN.txcoord.xy).x;
	float scenefocus=tex2D(SamplerFocus, 0.5).x;
	res.xyz=origcolor.xyz;

	float depth=linearlizeDepth(scenedepth);


	#ifdef AUTO_FOCUS
		float focalPlaneDepth=scenefocus;
		float farBlurDepth=scenefocus*pow(4.0, FarBlurCurve);
	#else
		float focalPlaneDepth=FocalPlaneDepth;
		float farBlurDepth=FarBlurDepth;
	#endif
	
	#ifdef TILT_SHIFT
		float shiftAngle=(frac(TiltShiftAngle / 90.0) == 0) ? 0.0 : TiltShiftAngle;
		float depthShift=1.0 + (0.5 - coord.x)*tan(-shiftAngle * 0.017453292);
		focalPlaneDepth*=depthShift;
		farBlurDepth*=depthShift;
	#endif
	
	
	if(depth < focalPlaneDepth)
		res.w=(depth - focalPlaneDepth)/focalPlaneDepth;
	else
	{
		res.w=(depth - focalPlaneDepth)/(farBlurDepth - focalPlaneDepth);
		res.w=saturate(res.w);
	}

	res.w=res.w * 0.5 + 0.5;
	
	#ifdef NOT_BLURRING_SKY_MODE
		#define	DEPTH_OF_FIELD_QULITY 0
		res.w=(depth > 1000.0) ? 0.5 : res.w;
	#endif

	
	return res;
}

float4 PS_ProcessPass2(VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{
	float4 res;
	
	float2 coord=IN.txcoord.xy;

	float4 origcolor=tex2D(InputSampler, coord.xy);
	
	float centerDepth=origcolor.w;

	
	float2 pixelSize=ScreenSize.y;
	pixelSize.y*=ScreenSize.z;
	
	float blurAmount=abs(centerDepth * 2.0 - 1.0);
	float discRadius=blurAmount * float(DEPTH_OF_FIELD_QULITY);
	discRadius*=RadiusSacleMultipiler;
	
	#ifdef AUTO_FOCUS
		discRadius*=(centerDepth < 0.5) ? (1.0 / max(NearBlurCurve, 1.0)) : 1.0;
	#endif
	
	
	res.xyz=origcolor.xyz;
	res.w=dot(res.xyz, 0.3333);
	res.w=max((res.w - BokehBrightnessThreshold) * BokehBrightnessMultipiler, 0.0);
	res.xyz*=1.0 + res.w*blurAmount;
	
	res.w=1.0;
	
	int sampleCycle=0;
	int sampleCycleCounter=0;
	int sampleCounterInCycle=0;
	
	#ifdef POLYGONAL_BOKEH
		float basedAngle=360.0 / POLYGON_NUM;
		float2 currentVertex;
		float2 nextVertex;
	
		int	dofTaps=DEPTH_OF_FIELD_QULITY * (DEPTH_OF_FIELD_QULITY + 1) * POLYGON_NUM / 2.0;
	#else
		int	dofTaps=DEPTH_OF_FIELD_QULITY * (DEPTH_OF_FIELD_QULITY + 1) * 4;
	#endif
		
	
	for(int i=0; i < dofTaps; i++)
	{
		if(sampleCounterInCycle % sampleCycle == 0) 
		{
			sampleCounterInCycle=0;
			sampleCycleCounter++;
		
			#ifdef POLYGONAL_BOKEH
				sampleCycle+=POLYGON_NUM;
				currentVertex.xy=float2(1.0 , 0.0);
				sincos(basedAngle* 0.017453292, nextVertex.y, nextVertex.x);	
			#else	
				sampleCycle+=8;
			#endif
		}
		sampleCounterInCycle++;
		
		#ifdef POLYGONAL_BOKEH
			float sampleAngle=basedAngle / float(sampleCycleCounter) * sampleCounterInCycle;
			float remainAngle=frac(sampleAngle / basedAngle) * basedAngle;
		
			if(remainAngle == 0)
			{
				currentVertex=nextVertex;
				sincos((sampleAngle +  basedAngle) * 0.017453292, nextVertex.y, nextVertex.x);
			}

			float2 sampleOffset=lerp(currentVertex.xy, nextVertex.xy, remainAngle / basedAngle);
		#else
			float sampleAngle=0.78539816 / float(sampleCycleCounter) * sampleCounterInCycle;
			float2 sampleOffset;
			sincos(sampleAngle, sampleOffset.y, sampleOffset.x);
		#endif
		
		sampleOffset*=sampleCycleCounter / float(DEPTH_OF_FIELD_QULITY);
		float2  coordLow=coord.xy + (pixelSize.xy * sampleOffset.xy * discRadius);
		float4 tap=tex2D(InputSampler, coordLow.xy);
		
		float weight=(tap.w >= centerDepth) ? 1.0 : abs(tap.w * 2.0 - 1.0);
		
		float luma=dot(tap.xyz, 0.3333);
		float brightMultipiler=max((luma - BokehBrightnessThreshold) * BokehBrightnessMultipiler, 0.0);
		tap.xyz*=1.0 + brightMultipiler*abs(tap.w*2.0 - 1.0);
		
		tap.xyz*=1.0 + BokehBias * pow(float(sampleCycleCounter)/float(DEPTH_OF_FIELD_QULITY), BokehBiasCurve);
		
	    res.xyz+=tap.xyz * weight;
	    res.w+=weight;
	}

	res.xyz /= res.w;
		
	res.w=centerDepth;


	return res;
}


float4 PS_ProcessPass3(VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{	
	float2 coord=IN.txcoord.xy;
	
	float2 pixelSize=ScreenSize.y;
	pixelSize.y*=ScreenSize.z;
	
	float4 origcolor=tex2D(InputSampler, coord.xy);
	float depth=origcolor.w;
	float blurAmount=abs(depth * 2.0 - 1.0);
	float discRadius=blurAmount * float(DEPTH_OF_FIELD_QULITY) * RadiusSacleMultipiler;
	
	#ifdef AUTO_FOCUS
		discRadius*=(depth < 0.5) ? (1.0 / max(NearBlurCurve, 1.0)) : 1.0;
	#endif
	
	float4 res=origcolor;
	
	float3 distortion=float3(-1.0, 0.0, 1.0);
	distortion*=ChromaticAberrationAmount*discRadius;

	origcolor=tex2D(InputSampler, coord.xy + pixelSize.xy*distortion.x);
	origcolor.w=smoothstep(0.0, depth, origcolor.w);
	res.x=lerp(res.x, origcolor.x, origcolor.w);
	
	origcolor=tex2D(InputSampler, coord.xy + pixelSize.xy*distortion.z);
	origcolor.w=smoothstep(0.0, depth, origcolor.w);
	res.z=lerp(res.z, origcolor.z, origcolor.w);

	return res;
}

float4 PS_ProcessPass4(VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{
	float2 coord=IN.txcoord.xy;
	
	float2 pixelSize=ScreenSize.y;
	pixelSize.y*=ScreenSize.z;
	
	float4 origcolor=tex2D(InputSampler, coord.xy);
	float depth=origcolor.w;
	float blurAmount=abs(depth*2.0 - 1.0);
	
	#if (DEPTH_OF_FIELD_QULITY > 0)
		#ifdef AUTO_FOCUS
			blurAmount*=(depth < 0.5) ? (1.0 / max(NearBlurCurve, 1.0)) : 1.0;
		#endif
		blurAmount=smoothstep(0.15, 1.0, blurAmount);
	#endif
	
	float weight[5] = {0.2270270270, 0.1945945946, 0.1216216216, 0.0540540541, 
		0.0162162162};
	
	float4 res=origcolor * weight[0];
	
	for(int i=1; i < 5; i++)
	{
		res+=tex2D(InputSampler, coord.xy + float2(i*pixelSize.x*blurAmount, 0)) * weight[i];
		res+=tex2D(InputSampler, coord.xy - float2(i*pixelSize.x*blurAmount, 0)) * weight[i];
	}
	
	
	res.w=depth;
	
	return res;
}

float4 PS_ProcessPass5(VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{
	float2 coord=IN.txcoord.xy;
	
	float2 pixelSize=ScreenSize.y;
	pixelSize.y*=ScreenSize.z;
	
	
	float4 origcolor=tex2D(InputSampler, coord.xy);
	float depth=origcolor.w;
	float blurAmount=abs(depth*2.0 - 1.0);
	
	#if (DEPTH_OF_FIELD_QULITY > 0)
		#ifdef AUTO_FOCUS
			blurAmount*=(depth < 0.5) ? (1.0 / max(NearBlurCurve, 1.0)) : 1.0;
		#endif
		blurAmount=smoothstep(0.15, 1.0, blurAmount);
	#endif
	
	float weight[5] = {0.2270270270, 0.1945945946, 0.1216216216, 0.0540540541, 
		0.0162162162};
	float4 res=origcolor * weight[0];

	for(int i=1; i < 5; i++)
	{
		res+=tex2D(InputSampler, coord.xy + float2(0, i*pixelSize.y*blurAmount)) * weight[i];
		res+=tex2D(InputSampler, coord.xy - float2(0, i*pixelSize.y*blurAmount)) * weight[i];
	}
	
	
	float origgray=dot(res.xyz, 0.3333);
	origgray/=origgray + 1.0;
	coord.xy=IN.txcoord.xy*16.0 + origgray;
	float4 cnoi=tex2D(SamplerNoise, coord);
	float noiseAmount=NoiseAmount*pow(blurAmount, NoiseCurve);
	res=lerp(res, (cnoi.x+0.5)*res, noiseAmount*saturate(1.0-origgray*1.8));
	
	res.w=depth;
	
	
	return res;
}
#endif

//--------------------------------------------------------------------------------------
// Compiler
//--------------------------------------------------------------------------------------
technique PostProcess
{	
	pass P0
	{
		VertexShader = compile vs_3_0 VS_PostProcess();
		PixelShader  = compile ps_3_0 main();
	}
#ifdef LIGHTSCATTERING
	pass P1
	{
		VertexShader = compile vs_3_0 VS_PostProcess();
		PixelShader  = compile ps_3_0 PS_ProcessSunShafts();
		AlphaBlendEnable=True;
		SrcBlend = One;
		DestBlend = One;
	}
#endif
#ifdef MATSO_FLARE
        pass P2
        {
                AlphaBlendEnable = true;
                SrcBlend = One;
                DestBlend = One;
                               
                PixelShader = compile ps_3_0 PS_ProcessPass_Anamorphic(fFlareAxis);
         }
#endif
}


technique PostProcess2
{	
	pass P0
	{
		VertexShader = compile vs_3_0 VS_PostProcess();
		PixelShader  = compile ps_3_0 CBloom();
	}
	#ifdef NOISE
	pass P1
	{

		VertexShader = compile vs_3_0 VS_PostProcess();
		PixelShader  = compile ps_3_0 PS_ProcessPass_ImageGrain();

		DitherEnable=FALSE;
		ZEnable=FALSE;
		CullMode=NONE;
		ALPHATESTENABLE=FALSE;
		SEPARATEALPHABLENDENABLE=FALSE;
		AlphaBlendEnable=FALSE;
		StencilEnable=FALSE;
		FogEnable=FALSE;
		SRGBWRITEENABLE=FALSE;
	}
	#endif
	#ifdef CHROMATICABBERATION
	pass P2
	{

		VertexShader = compile vs_3_0 VS_PostProcess();
		PixelShader  = compile ps_3_0 PS_PostProcessChroma();

		DitherEnable=FALSE;
		ZEnable=FALSE;
		CullMode=NONE;
		ALPHATESTENABLE=FALSE;
		SEPARATEALPHABLENDENABLE=FALSE;
		AlphaBlendEnable=FALSE;
		StencilEnable=FALSE;
		FogEnable=FALSE;
		SRGBWRITEENABLE=FALSE;
	}
	#endif	
}


#ifdef ADOF
technique PostProcess3
{
	pass P0
	{

		VertexShader = compile vs_3_0 VS_PostProcess();
		PixelShader  = compile ps_3_0 PS_ProcessPass1();

		DitherEnable=FALSE;
		ZEnable=FALSE;
		CullMode=NONE;
		ALPHATESTENABLE=FALSE;
		SEPARATEALPHABLENDENABLE=FALSE;
		AlphaBlendEnable=FALSE;
		StencilEnable=FALSE;
		FogEnable=FALSE;
		SRGBWRITEENABLE=FALSE;
	}
}


technique PostProcess4
{
	pass P0
	{

		VertexShader = compile vs_3_0 VS_PostProcess();
		PixelShader  = compile ps_3_0 PS_ProcessPass2();

		DitherEnable=FALSE;
		ZEnable=FALSE;
		CullMode=NONE;
		ALPHATESTENABLE=FALSE;
		SEPARATEALPHABLENDENABLE=FALSE;
		AlphaBlendEnable=FALSE;
		StencilEnable=FALSE;
		FogEnable=FALSE;
		SRGBWRITEENABLE=FALSE;
	}
}


technique PostProcess5
{
	pass P0
	{

		VertexShader = compile vs_3_0 VS_PostProcess();
		PixelShader  = compile ps_3_0 PS_ProcessPass3();

		DitherEnable=FALSE;
		ZEnable=FALSE;
		CullMode=NONE;
		ALPHATESTENABLE=FALSE;
		SEPARATEALPHABLENDENABLE=FALSE;
		AlphaBlendEnable=FALSE;
		StencilEnable=FALSE;
		FogEnable=FALSE;
		SRGBWRITEENABLE=FALSE;
	}
}


technique PostProcess6
{
	pass P0
	{

		VertexShader = compile vs_3_0 VS_PostProcess();
		PixelShader  = compile ps_3_0 PS_ProcessPass4();

		DitherEnable=FALSE;
		ZEnable=FALSE;
		CullMode=NONE;
		ALPHATESTENABLE=FALSE;
		SEPARATEALPHABLENDENABLE=FALSE;
		AlphaBlendEnable=FALSE;
		StencilEnable=FALSE;
		FogEnable=FALSE;
		SRGBWRITEENABLE=FALSE;
	}
}

technique PostProcess7
{
	pass P0
	{

		VertexShader = compile vs_3_0 VS_PostProcess();
		PixelShader  = compile ps_3_0 PS_ProcessPass5();

		DitherEnable=FALSE;
		ZEnable=FALSE;
		CullMode=NONE;
		ALPHATESTENABLE=FALSE;
		SEPARATEALPHABLENDENABLE=FALSE;
		AlphaBlendEnable=FALSE;
		StencilEnable=FALSE;
		FogEnable=FALSE;
		SRGBWRITEENABLE=FALSE;
	}
}

#endif






